package timing.ukulele.third.config.mp;

import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.api.WxConsts;
import me.chanjar.weixin.mp.api.WxMpMessageRouter;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.api.impl.WxMpServiceImpl;
import me.chanjar.weixin.mp.constant.WxMpEventConstants;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.core.RedisTemplate;
import timing.ukulele.common.dictionary.YesOrNoEnum;
import timing.ukulele.third.config.open.WxOpenConfiguration;
import timing.ukulele.third.handler.*;
import timing.ukulele.third.persistent.weixin.WxApp;
import timing.ukulele.third.service.weixin.WxAppService;

/**
 * 公众号Configuration
 * @author www.joolun.com
 *
 */
@Slf4j
@Configuration
public class WxMpConfiguration {

    private static RedisTemplate redisTemplate;
    private static WxAppService wxAppService;
    private static LogHandler logHandler;
    private static NullHandler nullHandler;
    private static KfSessionHandler kfSessionHandler;
    private static StoreCheckNotifyHandler storeCheckNotifyHandler;
    private static LocationHandler locationHandler;
    private static MenuHandler menuHandler;
    private static MsgHandler msgHandler;
    private static UnSubscribeHandler unSubscribeHandler;
    private static SubscribeHandler subscribeHandler;
    private static MassMsgHandler massMsgHandler;
    private static UserGetCardHandler userGetCardHandler;
    private static UserDelCardHandler userDelCardHandler;
    private static UserActivateCardHandler userActivateCardHandler;

    @Autowired
    public WxMpConfiguration(LogHandler logHandler, NullHandler nullHandler
            , KfSessionHandler kfSessionHandler, StoreCheckNotifyHandler storeCheckNotifyHandler
            , LocationHandler locationHandler, MenuHandler menuHandler
            , MsgHandler msgHandler, UnSubscribeHandler unSubscribeHandler
            , SubscribeHandler subscribeHandler, MassMsgHandler massMsgHandler
            , UserGetCardHandler userGetCardHandler, UserDelCardHandler userDelCardHandler
            , UserActivateCardHandler userActivateCardHandler
            , RedisTemplate redisTemplate, WxAppService wxAppService) {
        this.logHandler = logHandler;
        this.nullHandler = nullHandler;
        this.kfSessionHandler = kfSessionHandler;
        this.storeCheckNotifyHandler = storeCheckNotifyHandler;
        this.locationHandler = locationHandler;
        this.menuHandler = menuHandler;
        this.msgHandler = msgHandler;
        this.unSubscribeHandler = unSubscribeHandler;
        this.subscribeHandler = subscribeHandler;
        this.massMsgHandler = massMsgHandler;
        this.userGetCardHandler = userGetCardHandler;
        this.userDelCardHandler = userDelCardHandler;
        this.userActivateCardHandler = userActivateCardHandler;
        this.redisTemplate = redisTemplate;
        this.wxAppService = wxAppService;
    }

	/**
	 *  获取WxMpService
	 * @param id
	 * @return
	 */
	public static WxMpService getMpServiceById(Long id) {
		WxMpService wxMpService = null;
		WxApp wxApp = wxAppService.getById(id);
		if(wxApp != null) {
            // 第三方授权账号
			if(YesOrNoEnum.YES.getValue().equals(wxApp.getIsComponent())){
				wxMpService = WxOpenConfiguration.getOpenService().getWxOpenComponentService().getWxMpServiceByAppid(wxApp.getAppId());
			}else{
				WxMpInRedisConfigStorage configStorage = new WxMpInRedisConfigStorage(redisTemplate);
				configStorage.setAppId(wxApp.getAppId());
				configStorage.setSecret(wxApp.getSecret());
				configStorage.setToken(wxApp.getToken());
				configStorage.setAesKey(wxApp.getAesKey());
				wxMpService = new WxMpServiceImpl();
				wxMpService.setWxMpConfigStorage(configStorage);
			}
		}else{
			throw new RuntimeException("无此appID:"+wxApp.getAppId());
		}
		return wxMpService;
    }

    /**
     *  获取WxMpService
     * @param appId
     * @return
     */
    public static WxMpService getMpServiceByAppId(String appId) {
        WxMpService wxMpService = null;
        WxApp wxApp = wxAppService.findEntityByAppId(appId);
        if(wxApp!=null) {
            // 第三方授权账号
            if(YesOrNoEnum.YES.getValue().equals(wxApp.getIsComponent())){
                wxMpService = WxOpenConfiguration.getOpenService().getWxOpenComponentService().getWxMpServiceByAppid(appId);
            }else{
                WxMpInRedisConfigStorage configStorage = new WxMpInRedisConfigStorage(redisTemplate);
                configStorage.setAppId(wxApp.getAppId());
                configStorage.setSecret(wxApp.getSecret());
                configStorage.setToken(wxApp.getToken());
                configStorage.setAesKey(wxApp.getAesKey());
                wxMpService = new WxMpServiceImpl();
                wxMpService.setWxMpConfigStorage(configStorage);
            }
        }else{
            throw new RuntimeException("无此appID:"+appId);
        }
        return wxMpService;
    }

	/**
	 *  获取全局缓存WxMpMessageRouter
     *
	 * @param appId
	 * @return
	 */
	public static WxMpMessageRouter getWxMpMessageRouter(String appId) {
		WxMpMessageRouter wxMpMessageRouter = newRouter(getMpServiceByAppId(appId));
		return wxMpMessageRouter;
    }

	private static WxMpMessageRouter newRouter(WxMpService wxMpService) {
        final WxMpMessageRouter newRouter = new WxMpMessageRouter(wxMpService);

        // 记录所有事件的日志 （异步执行）
        newRouter.rule().handler(logHandler).next();

        // 接收客服会话管理事件
        newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT)
            .event(WxMpEventConstants.CustomerService.KF_CREATE_SESSION)
            .handler(kfSessionHandler).end();
        newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT)
            .event(WxMpEventConstants.CustomerService.KF_CLOSE_SESSION)
            .handler(kfSessionHandler)
            .end();
        newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT)
            .event(WxMpEventConstants.CustomerService.KF_SWITCH_SESSION)
            .handler(kfSessionHandler).end();

        // 门店审核事件
        newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT)
            .event(WxMpEventConstants.POI_CHECK_NOTIFY)
            .handler(storeCheckNotifyHandler).end();

        // 自定义菜单事件
        newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT)
            .event(WxConsts.MenuButtonType.CLICK).handler(menuHandler).end();

        // 点击菜单连接事件
        newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT)
            .event(WxConsts.MenuButtonType.VIEW).handler(menuHandler).end();

		// 扫码事件
		newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT)
				.event(WxConsts.EventType.SCANCODE_WAITMSG).handler(menuHandler).end();

        // 关注事件
        newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT)
            .event(WxConsts.EventType.SUBSCRIBE).handler(subscribeHandler)
            .end();

        // 取消关注事件
        newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT)
            .event(WxConsts.EventType.UNSUBSCRIBE)
            .handler(unSubscribeHandler).end();

        // 上报地理位置事件
        newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT)
            .event(WxConsts.EventType.LOCATION).handler(locationHandler)
            .end();

        // 卡券领取事件
        newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT)
            .event(WxConsts.EventType.CARD_USER_GET_CARD).handler(userGetCardHandler).end();

        // 卡券删除事件
        newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT)
            .event(WxConsts.EventType.CARD_USER_DEL_CARD).handler(userDelCardHandler).end();

        // 卡券激活事件
        newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT)
            .event(WxConsts.EventType.CARD_SUBMIT_MEMBERCARD_USER_INFO).handler(userActivateCardHandler).end();

		// 群发回调事件
		newRouter.rule().async(false).msgType(WxConsts.XmlMsgType.EVENT)
				.event(WxConsts.EventType.MASS_SEND_JOB_FINISH).handler(massMsgHandler).end();

        // 默认
        newRouter.rule().async(false).handler(msgHandler).end();

        return newRouter;
    }
}
